package jnpf.wx;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;

public class SingleOrderManager {

    // 替换为实际的签约编码
    private static final String MERCHANT_NO = "01202507241711050000";
    // 替换为实际的商户号
    private static final String PLATFORM_ID = "0100202507105302";
    // 接口地址
    private static final String SINGLE_ORDER_MANAGE_URL = "https://wxpay.cmbc.com.cn/mobilePlatform/bill/samSingleBillMannage.do";

    /**
     * 生成外部操作流水号（32位唯一）
     */
    private static String generateMerSerialNo() {
        return UUID.randomUUID().toString().replace("-", "") +
                UUID.randomUUID().toString().replace("-", "").substring(0, 8);
    }

    /**
     * 单笔订单管理接口调用
     * @param operType 操作类型（01-新增、02-修改、03-关闭）
     * @param billDetailNo 订单号
     * @param accType 子账簿类型（00-付款方子账簿、01-门店子账簿、02-待清分子账簿）
     * @param accNo 子账簿账号
     * @param billText 商品信息
     * @param subBillList 子订单列表
     * @param billAttach 商品备注
     * @param amount 订单金额
     * @param contractNo 合同编号
     * @param isPush 推送通知（00-不通知、01-短信、02-邮件、03-短信与邮件）
     * @param createUser 制单人
     * @param exactClearCond 精准核销条件
     * @return 接口响应JSON字符串
     */
    public static String manageSingleOrder(String operType, String billDetailNo, String accType, String accNo,
                                           String billText, List<JSONObject> subBillList, String billAttach,
                                           String amount, String contractNo, String isPush, String createUser,
                                           String exactClearCond) {
        // 1. 构建请求参数
        JSONObject requestData = new JSONObject();
        // 必传参数
        requestData.put("merchantNo", MERCHANT_NO);
        requestData.put("platformId", PLATFORM_ID);
        requestData.put("merSerialNo", MerSerialNoUtils.getFlowMchSeqNo());
        requestData.put("operType", operType);
        requestData.put("billDetailNo", billDetailNo);

        // 关闭操作只需上送订单号，其他必传参数根据操作类型处理
        if (!"03".equals(operType)) {
            requestData.put("accType", accType);
            requestData.put("accNo", accNo);
            requestData.put("amount", amount);
        }

        // 可选参数（非空才添加）
        if (billText != null && !billText.isEmpty()) {
            requestData.put("billText", billText);
        }
        if (subBillList != null && !subBillList.isEmpty()) {
            requestData.put("subBillList", subBillList);
        }
        if (billAttach != null && !billAttach.isEmpty()) {
            requestData.put("billAttach", billAttach);
        }
        if (contractNo != null && !contractNo.isEmpty()) {
            requestData.put("contractNo", contractNo);
        }
        if (isPush != null && !isPush.isEmpty()) {
            requestData.put("isPush", isPush);
        }
        if (createUser != null && !createUser.isEmpty()) {
            requestData.put("createUser", createUser);
        }
        if (exactClearCond != null && !exactClearCond.isEmpty()) {
            requestData.put("exactClearCond", exactClearCond);
        }

        // 2. 生成请求体JSON字符串
        String requestBody = requestData.toString();
        System.out.println("请求体：" + requestBody);

        // 3. 发送POST请求并返回响应
        return sendOrderRequest(requestBody);
    }

    /**
     * 发送订单管理请求
     * @param requestBody 请求体JSON字符串
     * @return 接口响应解密后的JSON字符串
     */
    public static String sendOrderRequest(String requestBody) {
        // 1. 校验请求体非空
        if (requestBody == null || requestBody.trim().isEmpty()) {
            throw new IllegalArgumentException("请求体不能为空（JSON报文缺失）");
        }

        // 2. 校验请求体为有效JSON
        if (!isValidJson(requestBody)) {
            throw new IllegalArgumentException("请求体不是有效的JSON格式：" + requestBody);
        }

        try {
            // 3. 加签、加密处理
            // 3.1 生成签名原文
            String sign = SignEncryptDncryptSignChk.getSign(requestBody);
            System.out.println("--------------------------------------");
            System.out.println("1. 签名原文（getSign）：");
            System.out.println(sign);

            // 3.2 用私钥加签
            String signContext = SignEncryptDncryptSignChk.sign(sign, requestBody);
            System.out.println("--------------------------------------");
            System.out.println("2. 加签后内容（sign）：");
            System.out.println(signContext);

            // 3.3 用银行公钥加密
            String encryptContext = SignEncryptDncryptSignChk.encrypt(signContext);
            System.out.println("--------------------------------------");
            System.out.println("3. 加密后内容（encrypt）：");
            System.out.println(encryptContext);

            // 4. 构建公共报文头
            JSONObject requestBodyPublicHeader = new JSONObject();
            requestBodyPublicHeader.put("businessContext", encryptContext);
            String requestJson = requestBodyPublicHeader.toString();
            System.out.println("--------------------------------------");
            System.out.println("4. 最终请求体（含公共报文头）：");
            System.out.println(requestJson);

            // 5. 发送HTTP请求
            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
                HttpPost httpPost = new HttpPost(SINGLE_ORDER_MANAGE_URL);
                httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");

                StringEntity entity = new StringEntity(requestJson, StandardCharsets.UTF_8);
                httpPost.setEntity(entity);

                // 6. 处理响应
                try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                    int statusCode = response.getStatusLine().getStatusCode();
                    System.out.println("--------------------------------------");
                    System.out.println("5. 响应状态码：" + statusCode);

                    HttpEntity responseEntity = response.getEntity();
                    if (responseEntity != null) {
                        String responseBody = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
                        System.out.println("--------------------------------------");
                        System.out.println("6. 原始响应内容：");
                        System.out.println(responseBody);

                        // 7. 提取并解密响应
                        JSONObject responseJson = JSONObject.parseObject(responseBody);
                        String responseCipher = responseJson.getString("businessContext");
                        System.out.println("--------------------------------------");
                        System.out.println("7. 响应体中的businessContext：");
                        System.out.println(responseCipher);

                        String dncryptContext = SignEncryptDncryptSignChk.dncrypt(responseCipher);
                        System.out.println("--------------------------------------");
                        System.out.println("8. 解密后内容：");
                        System.out.println(dncryptContext);

                        // 8. 验证签名
                        String signChkResult = SignEncryptDncryptSignChk.signCheck(dncryptContext);
                        System.out.println("--------------------------------------");
                        System.out.println("9. 签名验证结果：");
                        System.out.println(signChkResult);

                        return dncryptContext;
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("单笔订单管理请求失败：" + e.getMessage(), e);
        }

        return null;
    }

    /**
     * 简单校验JSON格式
     */
    private static boolean isValidJson(String json) {
        json = json.trim();
        return (json.startsWith("{") && json.endsWith("}"))
                || (json.startsWith("[") && json.endsWith("]"));
    }

    /**
     * 示例用法
     */
    public static void main(String[] args) {
        try {
            // 示例：新增单笔订单
            String result = manageSingleOrder(
                    "01",                  // 操作类型：新增
                            "10101010101010101010101010101010",  // 订单号
                    "00",                  // 子账簿类型：付款方子账簿
                    "9902000307022210",    // 子账簿账号
                    "测试商品订单",         // 商品信息
                    null,                  // 子订单列表（暂为空）
                    "测试新增订单",         // 商品备注
                    "1.00",              // 订单金额
                    "CONTRACT123",         // 合同编号
                    "01",                  // 推送通知：短信
                    "张三",                // 制单人
                    "TEST001~TEST002"      // 精准核销条件
            );
            System.out.println("单笔订单管理结果：" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}